package com.superbytecode.common.response;

import com.superbytecode.common.enums.ResponseCodeEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;

import java.util.Map;
import java.util.Objects;

/**
 * All rights Reserved, Designed By www.super-bytecode.com
 *
 * @ProjectName: superbytecode-beacon
 * @Package: com.superbytecode.common.response
 * @ClassName: ResponseWrapper
 * @Description: [响应结果包装类/工具]
 * <p> </p>
 * @Author: [Lance Ting]
 * @Date: 2023/11/18 10:06
 * @Version: V1.0
 * @Copyright: 2023 www.super-bytecode.com Inc. All rights reserved.
 * TODO: 注意,本文件Lance Ting所作,如果转载或使用请标明具体出处!
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class ResponseWrapper<T> {
    /**
     * @see ResponseCodeEnum
     */
    @ApiModelProperty("结果状态码")
    private String code;
    /**
     *
     */
    @ApiModelProperty("返回消息")
    private String message;
    /**
     *
     */
    @ApiModelProperty("返回数据")
    private T data;
    /**
     * 返回扩展数据
     */
    @ApiModelProperty("返回扩展数据")
    private Map<String, Object> ext;
    /**
     *
     */
    @ApiModelProperty("链路id")
    private String traceId;

    // -------------------------------------------------------------------------------
    public static <T> ResponseWrapper<T> success() {
        return success(null);
    }

    public static <T> ResponseWrapper<T> success(T data) {
        return new ResponseWrapper<>(ResponseCodeEnum.SUCCESS, data);
    }

    // -------------------------------------------------------------------------------
    public static ResponseWrapper<Void> failure(IResponseCode responseCode, String detailMsg) {
        return new ResponseWrapper<>(responseCode.getCode(), responseCode.getMessage() + ":" + detailMsg);
    }

    public static <T> ResponseWrapper<T> failure(IResponseCode responseCode) {
        return new ResponseWrapper<>(responseCode.getCode(), responseCode.getMessage());
    }

    public static <T> ResponseWrapper<T> failure(String code, String message) {
        return new ResponseWrapper<>(code, message);
    }

    // -------------------------------------------------------------------------------
    @Trace
    public void setTraceId() {
        this.traceId = TraceContext.traceId();
    }

    public ResponseWrapper(String code, String message) {
        this.code = code;
        this.message = message;
        this.setTraceId();
    }

    public ResponseWrapper(IResponseCode responseCode) {
        this(responseCode.getCode(), responseCode.getMessage());
    }

    public ResponseWrapper(IResponseCode responseCode, T data) {
        this(responseCode);
        this.data = data;
    }

    public boolean ok() {
        return Objects.equals(this.code, ResponseCodeEnum.SUCCESS.getCode());
    }
}